home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / ofs / ofsIo.c < prev   
Encoding:
C/C++ Source or Header  |  1992-12-19  |  16.2 KB  |  560 lines

  1. /* 
  2.  * ofsIo.c --
  3.  *
  4.  *    Routines providing I/O for OFS domain files.
  5.  *
  6.  * Copyright 1990 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/ofs/ofsIo.c,v 1.6 92/03/06 12:04:36 mgbaker Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include <sprite.h>
  21. #include <fs.h>
  22. #include <fsutil.h>
  23. #include <fslcl.h>
  24. #include <fsNameOps.h>
  25. #include <fsio.h>
  26. #include <fsStat.h>
  27. #include <fsdm.h>
  28. #include <fscache.h>
  29. #include <ofs.h>
  30. #include <devBlockDevice.h>
  31.  
  32. #include <stdio.h>
  33.  
  34. static Sync_Lock ofsCleanerLock = Sync_LockInitStatic("Fs:ofsCleanerLock");
  35. #define    LOCKPTR    &ofsCleanerLock
  36.  
  37. static int ofsBlockCleaners = 0; /* Number of block cleaner processes in 
  38.                   * action. */
  39.  
  40. /*
  41.  * ofsBlockWritesPerFile - maximum number of blocks written for a file
  42.  * before switching to the next dirty file.
  43.  */
  44. int    ofsBlockWritesPerFile = 25;
  45.  
  46. extern void Ofs_CleanBlocks _ARGS_((ClientData data, Proc_CallInfo *callInfoPtr));
  47. static Boolean FileMatch _ARGS_((Fscache_FileInfo *cacheInfoPtr, 
  48.                 ClientData clientData));
  49.  
  50.  
  51. /*
  52.  *----------------------------------------------------------------------
  53.  *
  54.  * Ofs_FileBlockRead --
  55.  *
  56.  *    Read in a cache block.  This does a direct disk read if the
  57.  *    file is the 'physical file' used for file descriptors and
  58.  *    indirect blocks.  If it is a regular file data block, then
  59.  *    the indexing structure is used to locate the file on disk.
  60.  *    This always attempts to read in a full block, but will read
  61.  *    less if at the last block and it isn't full.  In this case,
  62.  *    the remainder of the cache block is zero-filled.
  63.  *
  64.  * Results:
  65.  *    The results of the disk read.
  66.  *
  67.  * Side effects:
  68.  *    The buffer is filled with the number of bytes indicated by
  69.  *    the bufSize parameter.  The blockPtr->blockSize is modified to
  70.  *    reflect how much data was actually read in.  The unused part
  71.  *    of the block is filled with zeroes so that higher levels can
  72.  *    always assume the block has good stuff in all parts of it.
  73.  *
  74.  *----------------------------------------------------------------------
  75.  */
  76. /*ARGSUSED*/
  77. ReturnStatus
  78. Ofs_FileBlockRead(domainPtr, handlePtr, blockPtr)
  79.     Fsdm_Domain        *domainPtr;    /* Domain of file. */
  80.     register Fsio_FileIOHandle *handlePtr;    /* Handle on a local file. */
  81.     Fscache_Block    *blockPtr;    /* Cache block to read in.  This assumes
  82.                      * the blockNum, blockAddr (buffer area)
  83.                      * and blockSize are set.  This modifies
  84.                      * blockSize if less bytes were read
  85.                      * because of EOF. */
  86. {
  87.     register Ofs_Domain        *ofsPtr = OFS_PTR_FROM_DOMAIN(domainPtr);
  88.     register    Fsdm_FileDescriptor *descPtr;
  89.     register             offset;
  90.     register int         numBytes;
  91.     ReturnStatus         status;
  92.     OfsBlockIndexInfo         indexInfo;
  93.  
  94.     status = SUCCESS;
  95.     blockPtr->blockSize = 0;
  96.     numBytes = FS_BLOCK_SIZE;
  97.     offset = blockPtr->blockNum * FS_BLOCK_SIZE;
  98.  
  99.     if (handlePtr->hdr.fileID.minor == 0) {
  100.     /*
  101.      * If is a physical block address then read it in directly.
  102.      */
  103.     status = OfsDeviceBlockIO(ofsPtr, FS_READ, 
  104.                offset / FS_FRAGMENT_SIZE, FS_FRAGMENTS_PER_BLOCK, 
  105.                blockPtr->blockAddr);
  106.     fs_Stats.gen.physBytesRead += FS_BLOCK_SIZE;
  107.     } else {
  108.     /*
  109.      * Is a logical file read. Round the size down to the actual
  110.      * last byte in the file.
  111.      */
  112.  
  113.     descPtr = handlePtr->descPtr;
  114.     if (offset > descPtr->lastByte) {
  115.         numBytes = 0;
  116.         goto exit;
  117.     } else if (offset + numBytes - 1 > descPtr->lastByte) {
  118.         numBytes = descPtr->lastByte - offset + 1;
  119.     }
  120.  
  121.     status = OfsGetFirstIndex(ofsPtr, handlePtr, offset / FS_BLOCK_SIZE, 
  122.                  &indexInfo, 0);
  123.     if (status != SUCCESS) {
  124.         printf("Ofs_FileRead: Could not setup indexing\n");
  125.         goto exit;
  126.     }
  127.  
  128.     if (indexInfo.blockAddrPtr != (int *) NIL &&
  129.         *indexInfo.blockAddrPtr != FSDM_NIL_INDEX) {
  130.         /*
  131.          * Read in the block.  Specify the device, the fragment index,
  132.          * the number of fragments, and the memory buffer.
  133.          */
  134.         status = OfsDeviceBlockIO(ofsPtr, FS_READ, 
  135.               *indexInfo.blockAddrPtr +
  136.               ofsPtr->headerPtr->dataOffset * FS_FRAGMENTS_PER_BLOCK,
  137.               (numBytes - 1) / FS_FRAGMENT_SIZE + 1,
  138.               blockPtr->blockAddr);
  139.     } else {
  140.         /*
  141.          * Zero fill the block.  We're in a 'hole' in the file.
  142.          */
  143.         fs_Stats.blockCache.readZeroFills++;
  144.         bzero(blockPtr->blockAddr, numBytes);
  145.     }
  146.     OfsEndIndex(handlePtr, &indexInfo, FALSE);
  147.     Fs_StatAdd(numBytes, fs_Stats.gen.fileBytesRead,
  148.            fs_Stats.gen.fileReadOverflow);
  149.     }
  150. exit:
  151.     /*
  152.      * Define the block size and error fill leftover space.
  153.      */
  154.     if (status == SUCCESS) {
  155.     blockPtr->blockSize = numBytes;
  156.     }
  157.     if (blockPtr->blockSize < FS_BLOCK_SIZE) {
  158.     fs_Stats.blockCache.readZeroFills++;
  159.     bzero(blockPtr->blockAddr + blockPtr->blockSize,
  160.         FS_BLOCK_SIZE - blockPtr->blockSize);
  161.     }
  162.     return(status);
  163. }
  164.  
  165. /*
  166.  *----------------------------------------------------------------------
  167.  *
  168.  * Ofs_FileBlockWrite --
  169.  *
  170.  *    Write out a cache block.  This understands about physical
  171.  *    block writes as opposed to file block writes, and it understands
  172.  *    that negative block numbers are used for indirect blocks (gag).
  173.  *    Physical blocks are numbered from the beginning of the disk,
  174.  *    and they are used for file descriptors and indirect blocks.
  175.  *    File blocks are numbered from the beginning of the data block
  176.  *    area, so an offset must be used to calculate their true address.
  177.  *
  178.  * Results:
  179.  *    The return code from the driver, or FS_DOMAIN_UNAVAILABLE if
  180.  *    the domain has been un-attached.
  181.  *
  182.  * Side effects:
  183.  *    The device write.
  184.  *
  185.  *----------------------------------------------------------------------
  186.  */
  187. /*ARGSUSED*/
  188. ReturnStatus
  189. Ofs_FileBlockWrite(domainPtr, handlePtr, blockPtr)
  190.     register    Fsdm_Domain     *domainPtr;
  191.     register Fsio_FileIOHandle *handlePtr;    /* I/O handle for the file. */
  192.     Fscache_Block *blockPtr;    /* Cache block to write out. */
  193. {
  194.     register Ofs_Domain    *ofsPtr = OFS_PTR_FROM_DOMAIN(domainPtr);
  195.     ReturnStatus        status;
  196.     int                diskBlock;
  197.  
  198.     if (handlePtr->hdr.fileID.minor == 0 || blockPtr->diskBlock < 0) {
  199.     /*
  200.      * The block number is a raw block number counting from the
  201.      * beginning of the domain.
  202.      * Descriptor blocks are indicated by a handle with a 0 file number 
  203.      * and indirect a negative block number (indirect blocks).
  204.      */
  205.     if (blockPtr->diskBlock < 0) {
  206.         diskBlock = -blockPtr->diskBlock;
  207.     } else {
  208.         diskBlock = blockPtr->diskBlock;
  209.     }
  210.     fs_Stats.gen.physBytesWritten += blockPtr->blockSize;
  211.     status = OfsDeviceBlockIO(ofsPtr, FS_WRITE,
  212.              diskBlock, FS_FRAGMENTS_PER_BLOCK, blockPtr->blockAddr);
  213.     } else {
  214.     /*
  215.      * The block number is relative to the start of the data blocks.
  216.      */
  217.     status = OfsVerifyBlockWrite(ofsPtr, blockPtr);
  218.     if (status == SUCCESS) {
  219.         status = OfsDeviceBlockIO(ofsPtr, FS_WRITE,
  220.            blockPtr->diskBlock + 
  221.            ofsPtr->headerPtr->dataOffset * FS_FRAGMENTS_PER_BLOCK,
  222.            (blockPtr->blockSize - 1) / FS_FRAGMENT_SIZE + 1,
  223.            blockPtr->blockAddr);
  224.         }
  225.     if (status == SUCCESS) {
  226.         Fs_StatAdd(blockPtr->blockSize, fs_Stats.gen.fileBytesWritten,
  227.            fs_Stats.gen.fileWriteOverflow);
  228.     }
  229.     }
  230.     return(status);
  231. }
  232.  
  233. /*
  234.  *----------------------------------------------------------------------
  235.  *
  236.  * OfsDeviceBlockIO --
  237.  *
  238.  *    Map a file system block address to a block device block address 
  239.  *    perform the requested operation.
  240.  *
  241.  * NOTE: This routine is temporary and should be replaced when the file system
  242.  *     is converted to use the async block io interface.
  243.  *
  244.  * Results:
  245.  *    The return status of the operation.
  246.  *
  247.  * Side effects:
  248.  *    Blocks may be written or read.
  249.  *
  250.  *----------------------------------------------------------------------
  251.  */
  252.  
  253. ReturnStatus
  254. OfsDeviceBlockIO(ofsPtr, readWriteFlag, fragNumber, numFrags, buffer)
  255.     Ofs_Domain    *ofsPtr;    /* Domain */
  256.     int readWriteFlag;        /* FS_READ or FS_WRITE */
  257.     int fragNumber;        /* CAREFUL, fragment index, not block index.
  258.                  * This is relative to start of device. */
  259.     int numFrags;        /* CAREFUL, number of fragments, not blocks */
  260.     Address buffer;        /* I/O buffer */
  261. {
  262.     ReturnStatus status = SUCCESS;    /* General return code */
  263.     int firstSector;        /* Starting sector of transfer */
  264.     DevBlockDeviceRequest    request;
  265.     int                transferCount;
  266.  
  267.     if ((fragNumber % FS_FRAGMENTS_PER_BLOCK) != 0) {
  268.     /*
  269.      * The I/O doesn't start on a block boundary.  Transfer the
  270.      * first few extra fragments to get things going on a block boundary.
  271.      */
  272.     register int extraFrags;
  273.  
  274.     extraFrags = FS_FRAGMENTS_PER_BLOCK -
  275.             (fragNumber % FS_FRAGMENTS_PER_BLOCK);
  276.     if (extraFrags > numFrags) {
  277.         extraFrags = numFrags;
  278.     }
  279.     firstSector = OfsBlocksToSectors(fragNumber, 
  280.             &ofsPtr->headerPtr->geometry);
  281.     request.operation = readWriteFlag;
  282.     request.startAddress = firstSector * DEV_BYTES_PER_SECTOR;
  283.     request.startAddrHigh = 0;
  284.     request.bufferLen = extraFrags * FS_FRAGMENT_SIZE;
  285.     request.buffer = buffer;
  286.     status = Dev_BlockDeviceIOSync(ofsPtr->blockDevHandlePtr, &request, 
  287.                     &transferCount);
  288.     extraFrags = transferCount / FS_FRAGMENT_SIZE;
  289.     fragNumber += extraFrags;
  290.     buffer += transferCount;
  291.     numFrags -= extraFrags;
  292.     if (status != SUCCESS) {
  293.         return(status);
  294.     }
  295.     }
  296.     while (numFrags >= FS_FRAGMENTS_PER_BLOCK) {
  297.     /*
  298.      * Transfer whole blocks.
  299.      */
  300.     firstSector = OfsBlocksToSectors(fragNumber, 
  301.             &ofsPtr->headerPtr->geometry);
  302.     request.operation = readWriteFlag;
  303.     request.startAddress = firstSector * DEV_BYTES_PER_SECTOR;
  304.     request.startAddrHigh = 0;
  305.     request.bufferLen = FS_BLOCK_SIZE;
  306.     request.buffer = buffer;
  307.     status = Dev_BlockDeviceIOSync(ofsPtr->blockDevHandlePtr, &request, 
  308.                     &transferCount);
  309.     fragNumber += FS_FRAGMENTS_PER_BLOCK;
  310.     buffer += FS_BLOCK_SIZE;
  311.     numFrags -= FS_FRAGMENTS_PER_BLOCK;
  312.     if (status != SUCCESS) {
  313.         return(status);
  314.     }
  315.     }
  316.     if (numFrags > 0) {
  317.     /*
  318.      * Transfer the left over fragments.
  319.      */
  320.     firstSector = OfsBlocksToSectors(fragNumber, 
  321.             &ofsPtr->headerPtr->geometry);
  322.     request.operation = readWriteFlag;
  323.     request.startAddress = firstSector * DEV_BYTES_PER_SECTOR;
  324.     request.startAddrHigh = 0;
  325.     request.bufferLen = numFrags * FS_FRAGMENT_SIZE;
  326.     request.buffer = buffer;
  327.     status = Dev_BlockDeviceIOSync(ofsPtr->blockDevHandlePtr, &request, 
  328.                     &transferCount);
  329.     }
  330.     return(status);
  331. }
  332.  
  333.  
  334. /*
  335.  *----------------------------------------------------------------------
  336.  *
  337.  * FsioVerifyBlockWrite --
  338.  *
  339.  *    Double check this block to make sure it seems like were writing
  340.  *    it to the right place.
  341.  *
  342.  * Results:
  343.  *    Error code if an inconsistency was detected.
  344.  *
  345.  * Side effects:
  346.  *    None.
  347.  *
  348.  *----------------------------------------------------------------------
  349.  */
  350. /*ARGSUSED*/
  351. ReturnStatus
  352. OfsVerifyBlockWrite(ofsPtr, blockPtr)
  353.     Ofs_Domain    *ofsPtr;
  354.     Fscache_Block *blockPtr;        /* Block about to be written out */
  355. {
  356.     ReturnStatus status = SUCCESS;
  357.     Fs_HandleHeader *hdrPtr = blockPtr->cacheInfoPtr->hdrPtr;
  358.     OfsBlockIndexInfo         indexInfo;
  359.  
  360.     if (blockPtr->fileNum != hdrPtr->fileID.minor) {
  361.     printf("FsioVerifyBlockWrite: block being written to wrong file\n");
  362.     printf("    Logical block %d block's file %d owning file %d \"%s\"\n",
  363.         blockPtr->blockNum, blockPtr->fileNum,
  364.         hdrPtr->fileID.minor, Fsutil_HandleName(hdrPtr));
  365.     return(FS_INVALID_ARG);
  366.     }
  367.     status = OfsGetFirstIndex(ofsPtr, (Fsio_FileIOHandle *)hdrPtr, 
  368.             blockPtr->blockNum, &indexInfo,
  369.             (int)FSCACHE_DONT_BLOCK);
  370.     if (status == FS_WOULD_BLOCK) {
  371.     /*
  372.      * No room in the cache for the index blocks needed to check.
  373.      * assume the write is ok.
  374.      */
  375.     return(SUCCESS);
  376.     } else if (status != SUCCESS) {
  377.     return(status);
  378.     }
  379.     if (indexInfo.blockAddrPtr == (int *)NIL ||
  380.     *indexInfo.blockAddrPtr == FSDM_NIL_INDEX) {
  381.     printf("FsioVerifyBlockWrite: no block index\n");
  382.     panic("    Logical block %d owning file %d \"%s\"\n",
  383.         blockPtr->blockNum, hdrPtr->fileID.minor, Fsutil_HandleName(hdrPtr));
  384.     status = FS_INVALID_ARG;
  385.     goto exit;
  386.     }
  387.     if (*indexInfo.blockAddrPtr != blockPtr->diskBlock) {
  388.     printf("OfsVerifyBlockWrite: disk block mismatch\n");
  389.     panic("    Logical block %d old disk block %d new %d owning file %d \"%s\"\n",
  390.         blockPtr->blockNum, *indexInfo.blockAddrPtr,
  391.         blockPtr->diskBlock,
  392.         hdrPtr->fileID.minor, Fsutil_HandleName(hdrPtr));
  393.     status = FS_INVALID_ARG;
  394.     goto exit;
  395.     }
  396.  
  397. exit:
  398.     OfsEndIndex((Fsio_FileIOHandle *)hdrPtr, &indexInfo, FALSE);
  399.     return(status);
  400. }
  401.  
  402. /*
  403.  * ----------------------------------------------------------------------------
  404.  *
  405.  * BlockMatch --
  406.  *
  407.  *     Cache backend block type match.  Ofs doesn't care about the 
  408.  *    order of blocks returned by GetDirtyBlocks.
  409.  *
  410.  * Results:
  411.  *    TRUE.
  412.  *
  413.  * Side effects:
  414.  *
  415.  * ----------------------------------------------------------------------------
  416.  */
  417. /*ARGSUSED*/
  418. Boolean
  419. BlockMatch(blockPtr, clientData)
  420.     Fscache_Block *blockPtr;
  421.     ClientData       clientData;
  422. {
  423.     return TRUE;
  424. }
  425.  
  426.  
  427. /*
  428.  * ----------------------------------------------------------------------------
  429.  *
  430.  * FileMatch --
  431.  *
  432.  *     Cache backend file match. Ofs will take any file the cache wants
  433.  *    it to write.
  434.  *
  435.  * Results:
  436.  *    TRUE.
  437.  *
  438.  * Side effects:
  439.  *
  440.  * ----------------------------------------------------------------------------
  441.  */
  442. /*ARGSUSED*/
  443. static Boolean
  444. FileMatch(cacheInfoPtr, clientData)
  445.     Fscache_FileInfo *cacheInfoPtr;
  446.     ClientData    clientData;
  447. {
  448.     return TRUE;
  449. }
  450.  
  451.  
  452. /*
  453.  * ----------------------------------------------------------------------------
  454.  *
  455.  * Ofs_StartWriteBack --
  456.  *
  457.  *     Start a block cleaner process for the specified domain.
  458.  *
  459.  * Results:
  460.  *    TRUE if a block cleaner was started.
  461.  *
  462.  * Side effects:
  463.  *    Number of block cleaner processes may be incremented.
  464.  *
  465.  * ----------------------------------------------------------------------------
  466.  */
  467. Boolean
  468. Ofs_StartWriteBack(backendPtr, fileFsynced)
  469.     Fscache_Backend *backendPtr;    /* Backend to start writeback. */
  470.     Boolean fileFsynced;        /* For ASPLOS only.  Remove when
  471.                      * that's done.  -Mary 2/15/92. */
  472. {
  473.     LOCK_MONITOR;
  474.     if (ofsBlockCleaners < fscache_MaxBlockCleaners) {
  475.     Proc_CallFunc(Ofs_CleanBlocks, (ClientData) backendPtr, 0);
  476.     ofsBlockCleaners++;
  477.     UNLOCK_MONITOR;
  478.     return TRUE;
  479.     }
  480.     UNLOCK_MONITOR;
  481.     return FALSE;
  482. }
  483.  
  484.  
  485. /*
  486.  * ----------------------------------------------------------------------------
  487.  *
  488.  *    Functions to clean dirty blocks.
  489.  *
  490.  * ----------------------------------------------------------------------------
  491.  */
  492.  
  493.  
  494. /*
  495.  * ----------------------------------------------------------------------------
  496.  *
  497.  * Ofs_CleanBlocks
  498.  *
  499.  *    Write all blocks on the dirty list to disk.  Called either from
  500.  *    a block cleaner process or synchronously during system shutdown.
  501.  *
  502.  * Results:
  503.  *         None.
  504.  *
  505.  * Side effects:
  506.  *         The dirty list is emptied.
  507.  *
  508.  * ----------------------------------------------------------------------------
  509.  */
  510. /*ARGSUSED*/
  511. void
  512. Ofs_CleanBlocks(data, callInfoPtr)
  513.     ClientData        data;        /* Background flag.  If TRUE it means
  514.                      * we are called from a block cleaner
  515.                      * process.  Otherwise we being called
  516.                      * synchrounously during a shutdown */
  517.     Proc_CallInfo    *callInfoPtr;    /* Not Used. */
  518. {
  519.     Fscache_Block    *blockPtr;
  520.     ReturnStatus        status;
  521.     int                lastDirtyBlock;
  522.     Fscache_FileInfo        *cacheInfoPtr;
  523.     Fscache_Backend        *backendPtr;
  524.     int                numWrites;
  525.  
  526.     backendPtr = (Fscache_Backend *) data;
  527.     cacheInfoPtr = Fscache_GetDirtyFile(backendPtr, TRUE, FileMatch, 
  528.                     (ClientData) NIL);
  529.     while (cacheInfoPtr != (Fscache_FileInfo *)NIL) {
  530.     blockPtr = Fscache_GetDirtyBlock(cacheInfoPtr, BlockMatch, 
  531.                     (ClientData) 0, &lastDirtyBlock);
  532.     numWrites = 0;
  533.     while (blockPtr != (Fscache_Block *) NIL) {
  534.         /*
  535.          * Write the block.
  536.          */
  537.         status = Fsdm_FileBlockWrite
  538.             (cacheInfoPtr->hdrPtr, blockPtr, lastDirtyBlock);
  539.         numWrites++;
  540.         Fscache_ReturnDirtyBlock(blockPtr, status);
  541.         if (numWrites < ofsBlockWritesPerFile) {
  542.         blockPtr = Fscache_GetDirtyBlock(cacheInfoPtr, BlockMatch, 
  543.                     (ClientData) 0, &lastDirtyBlock);
  544.         } else {
  545.         break;
  546.         }
  547.     }
  548.     Fscache_ReturnDirtyFile(cacheInfoPtr, FALSE);
  549.     cacheInfoPtr = Fscache_GetDirtyFile(backendPtr, TRUE, FileMatch, 
  550.                     (ClientData) NIL);
  551.     }
  552.     FscacheBackendIdle(backendPtr);
  553.     LOCK_MONITOR;
  554.     ofsBlockCleaners--;
  555.     UNLOCK_MONITOR;
  556. }
  557.  
  558.  
  559.  
  560.